﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace GDM.Hogar.Controles.ControlesPersonalizados.ImagenBoton
{
    public partial class ImageButton : PictureBox, IButtonControl
    {
        #region IButtonControl Members

        public DialogResult DialogResult { get; set; }

        public void NotifyDefault(bool value)
        {
            _isDefault = value;
        }

        public void PerformClick()
        {
            base.OnClick(EventArgs.Empty);
        }

        #endregion IButtonControl Members

        #region HoverImage

        private Image _mHoverImage;

        [Category("Appearance")]
        [Description("Image to show when the button is hovered over.")]
        public Image HoverImage
        {
            get { return _mHoverImage; }
            set { _mHoverImage = value; if (_hover) Image = value; }
        }

        #endregion HoverImage

        #region DownImage

        private Image _mDownImage;

        [Category("Appearance")]
        [Description("Image to show when the button is depressed.")]
        public Image DownImage
        {
            get { return _mDownImage; }
            set { _mDownImage = value; if (_down) Image = value; }
        }

        #endregion DownImage

        #region NormalImage

        private Image _mNormalImage;

        [Category("Appearance")]
        [Description("Image to show when the button is not in any other state.")]
        public Image NormalImage
        {
            get { return _mNormalImage; }
            set { _mNormalImage = value; if (!(_hover || _down)) Image = value; }
        }

        #endregion NormalImage

        private const int WM_KEYDOWN = 0x0100;
        private const int WM_KEYUP = 0x0101;
        private bool _down;
        private bool _hover;
        private bool _isDefault;

        #region Overrides

        [Browsable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [Category("Appearance")]
        [Description("The font used to display text in the control.")]
        public override Font Font
        {
            get
            {
                return base.Font;
            }
            set
            {
                base.Font = value;
            }
        }

        [Browsable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [Category("Appearance")]
        [Description("The text associated with the control.")]
        public override string Text
        {
            get
            {
                return base.Text;
            }
            set
            {
                base.Text = value;
            }
        }

        #endregion Overrides

        #region Description Changes

        [Description("Controls what type of border the ImageButton should have.")]
        public new BorderStyle BorderStyle { get { return base.BorderStyle; } set { base.BorderStyle = value; } }

        [Description("Controls how the ImageButton will handle image placement and control sizing.")]
        public new PictureBoxSizeMode SizeMode { get { return base.SizeMode; } set { base.SizeMode = value; } }

        #endregion Description Changes

        #region Hiding

        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new Image BackgroundImage { get { return base.BackgroundImage; } set { base.BackgroundImage = value; } }

        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new ImageLayout BackgroundImageLayout { get { return base.BackgroundImageLayout; } set { base.BackgroundImageLayout = value; } }

        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new Image ErrorImage { get { return base.ErrorImage; } set { base.ErrorImage = value; } }

        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new Image Image { get { return base.Image; } set { base.Image = value; } }

        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new String ImageLocation { get { return base.ImageLocation; } set { base.ImageLocation = value; } }

        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new Image InitialImage { get { return base.InitialImage; } set { base.InitialImage = value; } }

        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new bool WaitOnLoad { get { return base.WaitOnLoad; } set { base.WaitOnLoad = value; } }

        #endregion Hiding

        #region Events

        private bool _holdingSpace;

        public override bool PreProcessMessage(ref Message msg)
        {
            if (msg.Msg == WM_KEYUP)
            {
                if (_holdingSpace)
                {
                    if ((int)msg.WParam == (int)Keys.Space)
                    {
                        OnMouseUp(null);
                        PerformClick();
                    }
                    else if ((int)msg.WParam == (int)Keys.Escape
                        || (int)msg.WParam == (int)Keys.Tab)
                    {
                        _holdingSpace = false;
                        OnMouseUp(null);
                    }
                }
                return true;
            }
            else
            {
                if (msg.Msg == WM_KEYDOWN)
                {
                    if ((int)msg.WParam == (int)Keys.Space)
                    {
                        _holdingSpace = true;
                        OnMouseDown(null);
                    }
                    else if ((int)msg.WParam == (int)Keys.Enter)
                    {
                        PerformClick();
                    }
                    return true;
                }
                return base.PreProcessMessage(ref msg);
            }
        }

        protected override void OnLostFocus(EventArgs e)
        {
            _holdingSpace = false;
            OnMouseUp(null);
            base.OnLostFocus(e);
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            Focus();
            OnMouseUp(null);
            _down = true;
            if (_mDownImage != null)
                Image = _mDownImage;
            base.OnMouseDown(e);
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            _hover = false;
            Image = _mNormalImage;
            base.OnMouseLeave(e);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            _hover = true;
            if (_down)
            {
                if ((_mDownImage != null) && (Image != _mDownImage))
                    Image = _mDownImage;
            }
            else
                if (_mHoverImage != null)
                    Image = _mHoverImage;
                else
                    Image = _mNormalImage;
            base.OnMouseMove(e);
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            _down = false;
            if (_hover)
            {
                if (_mHoverImage != null)
                    Image = _mHoverImage;
            }
            else
                Image = _mNormalImage;
            base.OnMouseUp(e);
        }

        protected override void OnPaint(PaintEventArgs pe)
        {
            base.OnPaint(pe);
            if ((!string.IsNullOrEmpty(Text)) && pe != null && (base.Font != null))
            {
                var drawBrush = new SolidBrush(base.ForeColor);
                var drawStringSize = pe.Graphics.MeasureString(base.Text, base.Font);
                PointF drawPoint;
                if (base.Image != null)
                    drawPoint = new PointF(base.Image.Width / 2 - drawStringSize.Width / 2, base.Image.Height / 2 - drawStringSize.Height / 2);
                else
                    drawPoint = new PointF(Width / 2 - drawStringSize.Width / 2, Height / 2 - drawStringSize.Height / 2);
                pe.Graphics.DrawString(base.Text, base.Font, drawBrush, drawPoint);
            }
        }

        protected override void OnTextChanged(EventArgs e)
        {
            Refresh();
            base.OnTextChanged(e);
        }

        #endregion Events
    }
}